﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net;
using System.Net.Sockets;

using System.Threading;

using MBNCSUtil;

using System.Diagnostics;

namespace FSLS
{
    public class FSLSClient
    {
        TcpClient _client = null;

        ManualResetEvent _mre = null;
        int _clientId = -1;

        #region events
        public delegate void ConnectionDroppedDelegate(int clientId);
        public event ConnectionDroppedDelegate ConnectionDropped;

        public delegate void DataTransmissionDelegate(int clientId, byte[] data);
        public event DataTransmissionDelegate DataSent;
        public event DataTransmissionDelegate DataReceived;
        #endregion

        public FSLSClient(TcpClient client, int clientId, ManualResetEvent mre)
        {
            _client = client;
            _clientId = clientId;
            _mre = mre;
        }

        public byte ReadByte()
        {
            return ReadData(1)[0];
        }

        public byte[] ReadData()
        {
            return ReadData(_client.Available);
        }

        public byte[] ReadData(int amount)
        {
            if (amount < 0)
                throw new ArgumentOutOfRangeException("amount");

            byte[] buff = new byte[amount];

            try
            {
                _client.GetStream().Read(buff, 0, amount);
                if (DataReceived != null)
                    DataReceived(_clientId, buff);
            }
            catch (SocketException sex)
            {
                throw sex;
            }

            return buff;
        }

        public bool SendData(byte[] data)
        {
            try
            {
                _client.GetStream().Write(data, 0, data.Length);
                if (DataSent != null)
                    DataSent(_clientId, data);
            }
            catch (SocketException sex)
            {
                throw sex;
            }

            return true;
        }

        public void ClientMonitorCallback(object clientId)
        {
            while (_client.Connected)
            {
                if (_client.Available > 1)
                {
                    Debug.Print("{0} bytes of data available.", _client.Available);

                    short pakLength = BitConverter.ToInt16(ReadData(2), 0);
                    byte pakId = 0xff;
                    DataBuffer buff = new DataBuffer();
                    int bytesReceived = 2;
                    Debug.Print("Incoming packet of length {0}", pakLength);

                    while (bytesReceived < pakLength)
                    {
                        if (bytesReceived == 2)
                            pakId = ReadByte();
                        else
                            buff.InsertByte(ReadByte());
                        bytesReceived++;
                    }

                    Debug.Print("Packet received. Sending response...");

                    DataBuffer outBuf = new DataBuffer();
                    outBuf.InsertByte(pakId);
                    outBuf.InsertInt16(pakLength);
                    outBuf.InsertByteArray(buff.GetData());
                    SendData(outBuf.GetData());
                    Debug.Print("Response sent.");
                }
            }

            ConnectionDropped(_clientId);

            _mre.Set();
        }
    }
}
